#ifndef MPHTTPDISPATCHER_H
#define MPHTTPDISPATCHER_H

/******************************
 *
 * 名   称：   HTTP请求调度员
 * 用   途：   协调HttpConnection、HttpRequestMessage、HttpResponseMessage和HttpResponseTranslation完成Http请求
 * 作用范围：   建议仅程序集内使用
 * 创建时间：   2022-10-03
 * 备   注：   execute_request_async和execute_request 方法不可多次调用，多次调用将导致不可知的错误。
 *
 *  *HTTP 请求头(样例)
 *    POST / HTTP/1.1
 *    Host: BucketName.oss-cn-hangzhou.aliyuncs.com
 *    User-Agent: browser_data
 *    Content-Length：ContentLength
 *    Content-Type: multipart/form-data; boundary=9431149156168
 *
 *    --9431149156168
 *    Content-Disposition: form-data; name="key"
 *    key
 *    --9431149156168
 *    Content-Disposition: form-data; name="file"; filename="MyFilename.jpg"
 *    Content-Type: image/jpeg
 *    file_content
 *
 *
 * HTTP 返回数据包(样例)
 *    HTTP/1.1 200 OK
 *    x-oss-request-id: 3a8f-2e2d-7965-3ff9-51c875b*****
 *    x-oss-object-type: Normal
 *    Date: Fri, 24 Feb 2012 06:38:30 GMT
 *    Last-Modified: Fri, 24 Feb 2012 06:07:48 GMT
 *    ETag: "5B3C1A2E0563E1B002CC607C*****"
 *    Content-Type: image/jpg
 *    Content-Length: 344606
 *    Server: AliyunOSS
 *    [344606 bytes of object data]
 *
 *
 * 参考：
 *
 ******************************/

#include <memory>
#include <condition_variable>
#include <boost/asio/steady_timer.hpp>

#include "mpHttpConnectionManage.h"
#include "mpHttpRequestMessage.h"
#include "mpHttpResponseMessage.h"
#include "mpHttpResponseTranslation.h"


namespace MP{
namespace HTTP{
namespace INTERNAL{

class HttpDispatcherAsync : public std::enable_shared_from_this<HttpDispatcherAsync>
{
public:
    HttpDispatcherAsync(boost::asio::io_context& io_context,
                        HttpConnectionManage::ptr_s httpConnectionManage,
                        HttpRequestMessage::ptr_s httpRequestMessage,
                        HttpResponseMessage::ptr_s httpResponseMessage,
                        int connect_timeout,
                        int write_timeout,
                        int read_timeout);

    HttpDispatcherAsync(const HttpDispatcherAsync&) = delete;
    HttpDispatcherAsync& operator=(const HttpDispatcherAsync&) = delete;
    virtual ~HttpDispatcherAsync() = default;

public:
    //执行异步请求
    bool execute_request_async();
    //设置 通知请求进度
    void set_send_progress_callback(func_send_progress_callback&& send_progress_callback);
    //设置 通知异步请求完成
    void set_send_complete_callback(func_send_complete_callback&& send_complete_callback);

protected:
    //结束请求
    virtual void end_request(bool isComplete);
protected:
    //初始化
    void init();

    //DNS解析
    void resolveAsync(const std::string host,
                      unsigned short port);
    void resolveHandle(const boost::system::error_code& err,
                       const boost::asio::ip::tcp::resolver::results_type& endpoints);

    //建立Http连接
    void connectAsync(const boost::asio::ip::tcp::resolver::results_type& endpoints);
    void connectHandle(const boost::system::error_code& err);

    //SSL握手
    void handshakeAsync();
    void handshakeHandle(const boost::system::error_code& err);

    //发送数据
    void writeRequestStartUp();
    void writeRequestHeaderAsync();
    void writeRequestHeaderHandle(const boost::system::error_code& err,
                                  std::size_t length);
    void writePayloadStartUp();
    void writePayloadAsync();
    void writePayloadHandle(const boost::system::error_code& err,
                            std::size_t length);
    void writePayloadCompleteHandle(const boost::system::error_code& err,
                                    std::size_t length);
    //接收数据
    void readResponseDataStartUp();
    void readResponseDataAsync();
    void readResponseDataHandle(boost::system::error_code err, std::size_t length);
    void readResponseDataComplete();

    //异常处理
    void httpErrorHandle(MP::HTTP::HTTP_SEND_STATU_CODE err_code,
                         const std::string& err_msg);

    //定时器相关函数
    void enableDeadlineTimer(int seconds);
    void disableDeadlineTimer();
    void deadlineTimerHandle(const boost::system::error_code& err);
    //回调函数
    void progress_callback(std::size_t step,std::size_t current,std::size_t total);
    void complete_callback(HttpResponseMessage::ptr_s httpResponseMessage);

private:
    //构造输入引用
    boost::asio::io_context& _io_context;
    //构造输入指针
    HttpConnectionManage::ptr_s _httpConnectionManage;
    HttpRequestMessage::ptr_s _httpRequestMessage;
    HttpResponseMessage::ptr_s _httpResponseMessage;
    //构造输入值类型
    int _connect_timeout = 10;
    int _write_timeout = 20;
    int _read_timeout = 20;
    //构造函数初始化的内部变量
    boost::asio::ip::tcp::resolver _resolver;               //用于dns查询
    boost::asio::steady_timer _deadline_timer;              //用于处理异步请求超时(单位秒)
    HttpResponseTranslation _httpResponseTranslation;       //HTTP响应翻译员
    //函数输入（回调函数）
    func_send_progress_callback _send_progress_callback;    //展示请求进度（step = 1 connect ；step = 2 writeData ；step = 3 readData ；）
    func_send_complete_callback _send_complete_callback;    //异步请求完成
    //内部变量
    HttpConnection::ptr_s _httpConnectionSharedPtr;         //Http请求连接
    bool _is_stopped = false;                               //标识请求是否已停止
    bool _is_deadline_timer_async_wait = false;             //标识定时器是否已调用async_wait
    bool _is_deadline_timer_enable = false;                 //标识定时器是否启用
    std::size_t _write_payload_length = 0;                  //已写入数据大小
    std::vector<char> _read_buf;                            //一次读取的服务端响应的数据容器
};


class HttpDispatcher : public HttpDispatcherAsync{

public:
    HttpDispatcher(boost::asio::io_context& io_context,
                   HttpConnectionManage::ptr_s httpConnectionManage,
                   HttpRequestMessage::ptr_s httpRequestMessage,
                   HttpResponseMessage::ptr_s httpResponseMessage,
                   int connect_timeout,
                   int write_timeout,
                   int read_timeout)
        :HttpDispatcherAsync(io_context,httpConnectionManage,httpRequestMessage,httpResponseMessage,connect_timeout,write_timeout,read_timeout)
    {

    }

    ~HttpDispatcher() override = default;

public:
    //执行同步请求
    void execute_request();

protected:
    void end_request(bool isComplete) override;
private:
    bool _async_request_finished = true;
    std::condition_variable _async_request_cv;
    std::mutex _async_request_mutex;
};


}   //INTERNAL
}   //HTTP
}   //MP

#endif // MPHTTPDISPATCHER_H
